home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume4 / match1.2 < prev    next >
Encoding:
Internet Message Format  |  1986-11-30  |  25.3 KB

  1. From: genrad!decvax!linus!bnr-vpa!pdbain
  2. Subject: Match 1.2 - Fast grep for Vaxen
  3. Newsgroups: mod.sources
  4. Approved: jpn@panda.UUCP
  5.  
  6. Mod.sources:  Volume 4, Issue 51
  7. Submitted by: genrad!decvax!linus!bnr-vpa!pdbain
  8.  
  9.  
  10. This contains the same bug fixes as in the latest release of
  11. bm. Match is a very fast (faster than bm, much faster than grep)
  12. pattern matcher for Vax machines, using the MATCHC
  13. instruction. Be warned, though: some Vaxen (such as Microvax I)
  14. interpret the MATCHC instruction, and don't achieve the same performance.
  15.  
  16. *********************** cut here ******************************
  17. #! /bin/sh
  18. # This is a shell archive, meaning:
  19. # 1. Remove everything above the #! /bin/sh line.
  20. # 2. Save the resulting text in a file.
  21. # 3. Execute the file with /bin/sh (not csh) to create the files:
  22. #    README
  23. #    match.1
  24. #    Makefile
  25. #    Search.s
  26. #    Execute.c
  27. #    GetPatFile.c
  28. #    Global.c
  29. #    MakeDesc.c
  30. #    MatchFound.c
  31. #    MkDescVec.c
  32. #    MoveResidue.c
  33. #    PrintLine.c
  34. #    PutUsage.c
  35. #    match.c
  36. #    Extern.h
  37. #    match.h
  38. # This archive created: Fri Apr  4 09:54:35 1986
  39. export PATH; PATH=/bin:$PATH
  40. echo shar: extracting "'README'" '(1794 characters)'
  41. if test -f 'README'
  42. then
  43.     echo shar: will not over-write existing file "'README'"
  44. else
  45. cat << \SHAR_EOF > 'README'
  46. Match is a fast pattern matching utility, intended to be almost
  47. identical in functionality to fgrep (ugh!) but much faster. It uses
  48. MATCHC instruction on VAX computers. Apparently, it is faster than
  49. BM only on the VAX 780 - on the Microvax it is much slower than bm.
  50.  
  51. *** NOTE *** There are certain system dependencies in the code.
  52. Some systems use "index", others "strchr" to find a character in a
  53. string: this affects MkDescVec.c. A #ifdef checks this.
  54. Please check whether your system uses <strings.h> or <string.h>.
  55. If it uses strings.h, delete "-DSTRINGS" from the line
  56.     CFLAGS =  -O -DSTRINGS -DBCOPY
  57. in the Makefile.  This affects match.c/bm.c, MkDescVec.c, and PrintLine.c.
  58. Also check whether your system has "bcopy".
  59. If it uses strings.h, comment out "-DBCOPY" from the line
  60.     CFLAGS =  -O -DSTRINGS -DBCOPY
  61. in the Makefile. This affects MoveResidue.c
  62.  
  63. The files are:
  64. Execute.c: search a file for the patterns
  65. Extern.h: declarations of externs
  66. GetPatFile.c: read in patterns from a file and set up a vector of
  67.     pattern descriptors
  68. Global.c: global variables (complement to Extern.h)
  69. MakeDesc.c: create a pattern descriptor for one pattern
  70. Makefile: you can figure this one out for yourself
  71. MatchFound.c: what to do when you actually FIND a pattern - print it,
  72.     update flags, etc.
  73. MkDescVec.c: make a vector of pattern descriptors, given a string
  74.     of newline-separated patterns
  75. MoveResidue.c: when you come to the end of the buffer, move the
  76.     unsearched "residue" to the beginning and start again
  77. PrintLine.c: print the appropriate stuff after finding a match
  78. PutUsage.c: mini-man page.
  79. README: this file
  80. Search.s: the guts. Calls MATCH
  81. match.c: mainline. mostly interpreting the command line and tidying
  82.     up at the end. Calls Execute for each file.
  83. match.h: constants
  84. match.1: man page
  85. SHAR_EOF
  86. if test 1794 -ne "`wc -c < 'README'`"
  87. then
  88.     echo shar: error transmitting "'README'" '(should have been 1794 characters)'
  89. fi
  90. fi
  91. echo shar: extracting "'match.1'" '(2712 characters)'
  92. if test -f 'match.1'
  93. then
  94.     echo shar: will not over-write existing file "'match.1'"
  95. else
  96. cat << \SHAR_EOF > 'match.1'
  97. .TH MATCH PUBLIC "11 July 1985"
  98. .UC 4
  99. .SH NAME
  100. match \- search a file for a string
  101. .SH SYNOPSIS
  102. .B /usr/public/match
  103. [ option ] ...
  104. [ strings ]
  105. [ file ]
  106. .SH DESCRIPTION
  107. .I Match
  108. searches the input
  109. .I files
  110. (standard input default) for lines matching a string.
  111. Normally, each line found is copied to the standard output.
  112. It is blindingly fast.
  113. .I Match
  114. strings are fixed sequences of characters:
  115. there are no wildcards, repetitions, or other features
  116. of regular expressions.
  117. Match is also case sensitive.
  118. The following options are recognized.
  119. .TP
  120. .B \-x
  121. (Exact) only lines matched in their entirety are printed
  122. .TP
  123. .B \-l
  124. The names of files with matching lines are listed (once) separated by newlines.
  125. .TP
  126. .B \-c
  127. Only a count of the number of matches
  128. is printed
  129. .TP
  130. .B \-e "string"
  131. The string is the next argument after the
  132. .B \-e
  133. flag. This allows strings beginning with '-'.
  134. .TP
  135. .B \-h
  136. No filenames are printed, even if multiple files are searched.
  137. .TP
  138. .B \-n
  139. Each line is preceded by the number
  140. of characters from the beginning of the file
  141. to the match.
  142. .TP
  143. .B \-s
  144. Silent mode.  Nothing is printed (except error messages).
  145. This is useful for checking the error status.
  146. .TP
  147. .BI \-f " file"
  148. The string list
  149. is taken from the
  150. .I file.
  151. .LP
  152. Unless the
  153. .B \-h
  154. option is specified
  155. the file name is shown if there is more than one input file.
  156. Care should be taken when using the characters $ * [ ^ | ( ) and \\ in the
  157. .I strings
  158. (listed on the command line)
  159. as they are also meaningful to the Shell.  It is safest to enclose the entire
  160. .I expression
  161. argument in single quotes \' \'.
  162. .LP
  163. .I Match
  164. searches for lines that contain one of the (newline-separated)
  165. .I strings,
  166. using
  167. the VAX MATCHC instruction
  168. It is far superior in terms of speed to the grep (egrep, fgrep)
  169. family of pattern matchers, as well as bm(p) for fixed-pattern searching
  170. on a VAX 780.
  171. .SH "SEE ALSO"
  172. grep(1), bm(p)
  173. .SH DIAGNOSTICS
  174. Exit status is 0 if any matches are found,
  175. 1 if none, 2 for syntax errors or inaccessible files.
  176. .SH AUTHOR
  177. Peter Bain (pdbain@wateng)
  178. .SH BUGS
  179. Works slowly on VAXen other than the 780, and doesn't work at all
  180. on other architectures.
  181. .LP
  182. Only 100 patterns are allowed.
  183. .LP
  184. Patterns may not contain newlines.
  185. .LP
  186. If a line (delimited by newlines, and the beginning and end of the file)
  187. is longer than 8000 charcters (e.g. in a core dump),
  188. it will not be completely printed.
  189. .LP
  190. If multiple patterns are specified, the order of the ouput lines is not
  191. necessarily the same as the order of the input lines.
  192. .LP
  193. A line will be printed once for each different string on that line.
  194. .LP
  195. The algorithm cannot count lines.
  196. .LP
  197. The
  198. .B -n
  199. and
  200. .B -c
  201. work differently from fgrep.
  202. .LP
  203. The
  204. .B -v,
  205. .B -i,
  206. and
  207. .B -b
  208. are not available.
  209. SHAR_EOF
  210. if test 2712 -ne "`wc -c < 'match.1'`"
  211. then
  212.     echo shar: error transmitting "'match.1'" '(should have been 2712 characters)'
  213. fi
  214. fi
  215. echo shar: extracting "'Makefile'" '(1121 characters)'
  216. if test -f 'Makefile'
  217. then
  218.     echo shar: will not over-write existing file "'Makefile'"
  219. else
  220. cat << \SHAR_EOF > 'Makefile'
  221. CFLAGS =  -O -DSTRINGS -DBCOPY
  222. SOURCES =  Execute.c Extern.h\
  223.     GetPatFile.c Global.c MakeDesc.c \
  224.     match.h match.c MatchFound.c \
  225.     MkDescVec.c MoveResidue.c PrintLine.c PutUsage.c Search.s
  226. OBJECTS = Execute.o \
  227.     GetPatFile.o Global.o MakeDesc.o \
  228.     match.o MatchFound.o \
  229.     MkDescVec.o MoveResidue.o Search.o PrintLine.o PutUsage.o
  230. BASEFILES = $(SOURCES) Makefile README match.p
  231. match: $(OBJECTS)
  232.     cc -o match $(CFLAGS) $(OBJECTS)
  233. shar:
  234.     shar $(BASEFILES) >match.shar
  235. install: match
  236.     install -c -s match /usr/public/match
  237. man: /usr/man/manp/match.p
  238. /usr/man/manp/match.p: match.p
  239.     rm -f /usr/man/manp/match.p
  240.     cp match.p /usr/man/manp/match.p
  241.     man match > /dev/null
  242. match.o: match.c match.h Extern.h
  243. PutUsage.o: PutUsage.c match.h 
  244. Search.o: Search.s
  245. Execute.o: Execute.c match.h 
  246. MoveResidue.o: MoveResidue.c match.h Extern.h
  247. MatchFound.o: MatchFound.c match.h Extern.h
  248. PrintLine.o: PrintLine.c Extern.h
  249. MkDescVec.o: MkDescVec.c match.h
  250. GetPatFile.o: GetPatFile.c match.h
  251. MakeDesc.o: MakeDesc.c match.h
  252. Global.o: Global.c
  253. listing:
  254.     print -o3 $(BASEFILES) Makefile
  255. #    print -i3 $(BASEFILES) Makefile
  256. clean:
  257.     rm -f *.o match
  258. SHAR_EOF
  259. if test 1121 -ne "`wc -c < 'Makefile'`"
  260. then
  261.     echo shar: error transmitting "'Makefile'" '(should have been 1121 characters)'
  262. fi
  263. fi
  264. echo shar: extracting "'Search.s'" '(239 characters)'
  265. if test -f 'Search.s'
  266. then
  267.     echo shar: will not over-write existing file "'Search.s'"
  268. else
  269. cat << \SHAR_EOF > 'Search.s'
  270. LL0:
  271.     .data
  272.     .text
  273.     .align    1
  274.     .globl    _Search
  275. _Search:
  276.     .word    L20
  277.     matchc    8(ap),*4(ap),16(ap),*12(ap)
  278.     beql    match
  279.     movl    20(ap),r0
  280.     movl    r3,8(r0)
  281.     movl    $0,r0
  282.     ret
  283. match:
  284.     movl    20(ap),r0
  285.     movl    r3,8(r0)
  286.     movl    $1,r0
  287.     ret
  288.     .set    L20,0xf00
  289.     .data
  290. SHAR_EOF
  291. if test 239 -ne "`wc -c < 'Search.s'`"
  292. then
  293.     echo shar: error transmitting "'Search.s'" '(should have been 239 characters)'
  294. fi
  295. fi
  296. echo shar: extracting "'Execute.c'" '(2733 characters)'
  297. if test -f 'Execute.c'
  298. then
  299.     echo shar: will not over-write existing file "'Execute.c'"
  300. else
  301. cat << \SHAR_EOF > 'Execute.c'
  302. #include <stdio.h>
  303. #include "match.h"
  304. #include "Extern.h"
  305. Execute(DescVec, NPats, TextFile, Buffer)
  306. register struct PattDesc *DescVec[];
  307. /* pointers to status vectors for the different
  308.     * patterns, including skip tables, position in buffer, etc. */
  309. register int NPats; /* number of patterns */
  310. register char Buffer[]; /* holds text from file */
  311. register int TextFile; /* file to search */
  312. {
  313.     int NRead, /* number of chars read from file */
  314.         NWanted, /* number of chars wanted */
  315.         NAvail, /* number of chars actually read */
  316.         BuffSize, /* number of chars in buffer */
  317.         BuffPos, /* offset of first char in Buffer in TextFile */
  318.         BuffEx, /* flag to indicate that buffer has been searched */
  319.         ResSize,
  320.         /* number of characters in the last, incomplete line */
  321.         Found, /* flag indicates whether pattern found
  322.         * completely and all matches printed */
  323.         Valid; /* was the match "valid", i.e. if -x used,
  324.         * did the whole line match? */
  325.     register char *BuffEnd;
  326.     /* pointer to last char of last complete line */
  327.  
  328.     /* misc working variables */
  329.     register int i;
  330.  
  331.     /* initialize */
  332.     ResSize = 0;
  333.     Found = 0;
  334.     BuffPos = 0;
  335.     for (i=0; i < NPats; i++) {
  336.         DescVec[i] -> Success = 0;
  337.         DescVec[i] -> Start = Buffer;
  338.     } /* for */
  339.     /* now do the searching */
  340.     do {
  341.         /* first, read a bufferfull and set up the variables */
  342.         NWanted = MAXBUFF - ResSize; NRead = 0;
  343.         do {
  344.             NAvail =
  345.                read(TextFile,Buffer + ResSize + NRead, NWanted);
  346.             if (NAvail == -1) {
  347.                 fprintf(stderr,
  348.                   "bm: error reading from input file\n");
  349.                 exit(2);
  350.             } /* if */
  351.             NRead += NAvail; NWanted -= NAvail;
  352.         } while (NAvail && NWanted);
  353.         BuffEx = 0;
  354.         BuffSize = ResSize + NRead;
  355.         BuffEnd = Buffer + BuffSize - 1;
  356.         /* locate the end of the last complete line */
  357.         while (*BuffEnd != '\n' && BuffEnd >= Buffer)
  358.             --BuffEnd;
  359.         if (BuffEnd < Buffer)
  360.             BuffEnd = Buffer + BuffSize - 1;
  361.         while (!BuffEx) { /* work through one buffer full */
  362.             BuffEx = 1; /* set it provisionally, then clear
  363.             * it if we find the buffer non-empty */
  364.             for (i=0; i< NPats; i++) {
  365.                 if (!DescVec[i]->Success)
  366.                 /* if the pattern  has not been found */
  367.                     DescVec[i]-> Success =
  368.                     Search(DescVec[i]->Pattern,
  369.                     DescVec[i]->PatLen, DescVec[i]->Start,
  370.                     BuffEnd - DescVec[i]->Start + 1,
  371.                     DescVec[i]);
  372.                 if (DescVec[i]->Success){
  373.                 /* if a match occurred */
  374.                     BuffEx = 0;
  375.                     Valid = MatchFound(DescVec[i],BuffPos,
  376.                     Buffer, BuffEnd);
  377.                     Found |= Valid;
  378.                     if ((sFlag || lFlag) && Found)
  379.                         return(0);
  380.                 } /* if */
  381.             } /* for */
  382.         } /* while */
  383.         if(NRead) {
  384.             ResSize = MoveResidue(DescVec,NPats,Buffer,
  385.                 Buffer + BuffSize -1);
  386.             BuffPos += BuffSize - ResSize;
  387.         } /* if */
  388.     } while (NRead);
  389.     return(!Found);
  390. } /* Execute */
  391. SHAR_EOF
  392. if test 2733 -ne "`wc -c < 'Execute.c'`"
  393. then
  394.     echo shar: error transmitting "'Execute.c'" '(should have been 2733 characters)'
  395. fi
  396. fi
  397. echo shar: extracting "'GetPatFile.c'" '(1410 characters)'
  398. if test -f 'GetPatFile.c'
  399. then
  400.     echo shar: will not over-write existing file "'GetPatFile.c'"
  401. else
  402. cat << \SHAR_EOF > 'GetPatFile.c'
  403. #include <stdio.h>
  404. #include <sys/types.h>
  405. #include <sys/stat.h>
  406. #include "match.h"
  407. int
  408. GetPatFile(PatFile, DescVec)
  409. char *PatFile;
  410. struct PattDesc *DescVec[];
  411. /* read patterns from a file and set up a pattern descriptor vector */
  412. {
  413.     extern char *malloc();
  414.     FILE *PFile;
  415.     struct stat StatBuff;
  416.     int PatSize; /* the number of chars in all the patterns */
  417.     char *PatBuff; /* hold the patterns */
  418.     if (!(strlen(PatFile))) {
  419.         fprintf(stderr,"mathc: no pattern file given\n");
  420.         exit(2);
  421.     } /* if */
  422.     if (!(PFile = fopen(PatFile,"r"))) {
  423.         fprintf(stderr,"match: can't open pattern file %s\n",PatFile);
  424.         exit(2);
  425.     } /* if */
  426.     /* find out how big the patterns are */
  427.     if (fstat(fileno(PFile),&StatBuff) == -1) {
  428.         fprintf(stderr,"match: can't fstat %s\n",PatFile);
  429.         exit(2);
  430.     } /* if */
  431.     if (isatty(fileno(PFile)))
  432.         PatSize = PSIZEDEF;
  433.     else PatSize = StatBuff.st_size;
  434.     if (!PatSize) {
  435.         fprintf(stderr,"match: pattern file is empty\n");
  436.         exit(2);
  437.     } /* if */
  438.     if (!(PatBuff = malloc(PatSize + 1))) {
  439.            fprintf(stderr,"match: insufficient memory to store patterns\n");
  440.         exit(2);
  441.     } /* if */
  442.     fread(PatBuff,1,PatSize,PFile); /* get the patterns */
  443.     fclose(PFile);
  444.     /* make sure the patterns are null-terminated. We can't have
  445.     * nulls in the patterns */
  446.     if (PatBuff[PatSize-1] == '\n')
  447.         PatBuff[PatSize-1] = '\0';
  448.     else
  449.         PatBuff[PatSize] = '\0';
  450.     return(MkDescVec(DescVec,PatBuff));
  451. } /* GetPatFile */
  452. SHAR_EOF
  453. if test 1410 -ne "`wc -c < 'GetPatFile.c'`"
  454. then
  455.     echo shar: error transmitting "'GetPatFile.c'" '(should have been 1410 characters)'
  456. fi
  457. fi
  458. echo shar: extracting "'Global.c'" '(626 characters)'
  459. if test -f 'Global.c'
  460. then
  461.     echo shar: will not over-write existing file "'Global.c'"
  462. else
  463. cat << \SHAR_EOF > 'Global.c'
  464. /* global flags for match */
  465. int    cFlag=0, /* true if we want only a count of matching lines */
  466.     eFlag=0, /* indicates that next argument is the pattern */
  467.     fFlag=0, /* true if the patterns are to come from a file */
  468.     lFlag=0, /* true if we want a list of files containing the pattern */
  469.     nFlag=0, /* true if we want the character offset of the pattern */
  470.     sFlag=0, /* true if we want silent mode */
  471.     xFlag=0, /* true if we want only lines which match entirely */
  472.     hFlag=0, /* true if we want no filenames in output */
  473.  
  474.     MatchCount=0; /* count of number of times a search string was found
  475.     * in the text */
  476. char *FileName = 0;
  477. SHAR_EOF
  478. if test 626 -ne "`wc -c < 'Global.c'`"
  479. then
  480.     echo shar: error transmitting "'Global.c'" '(should have been 626 characters)'
  481. fi
  482. fi
  483. echo shar: extracting "'MakeDesc.c'" '(343 characters)'
  484. if test -f 'MakeDesc.c'
  485. then
  486.     echo shar: will not over-write existing file "'MakeDesc.c'"
  487. else
  488. cat << \SHAR_EOF > 'MakeDesc.c'
  489. #include <stdio.h>
  490. #include "match.h"
  491. #include "Extern.h"
  492. extern char * malloc();
  493. /* makes a pattern descriptor */
  494. struct PattDesc *MakeDesc(Pattern)
  495. char *Pattern;
  496. {
  497.     struct PattDesc *Desc;
  498.     Desc = (struct PattDesc *) malloc(sizeof(struct PattDesc));
  499.     Desc->Pattern=Pattern;
  500.     Desc->PatLen = strlen(Desc->Pattern);
  501.     return(Desc);
  502. } /* main */
  503. SHAR_EOF
  504. if test 343 -ne "`wc -c < 'MakeDesc.c'`"
  505. then
  506.     echo shar: error transmitting "'MakeDesc.c'" '(should have been 343 characters)'
  507. fi
  508. fi
  509. echo shar: extracting "'MatchFound.c'" '(1181 characters)'
  510. if test -f 'MatchFound.c'
  511. then
  512.     echo shar: will not over-write existing file "'MatchFound.c'"
  513. else
  514. cat << \SHAR_EOF > 'MatchFound.c'
  515. #include <stdio.h>
  516. #include "match.h"
  517. #include "Extern.h"
  518. MatchFound(Desc, BuffPos, Buffer, BuffEnd)
  519. struct PattDesc *Desc; /* state info about search for one string */
  520. int BuffPos; /* offset of first char of buffer into the file being searched */
  521. char *Buffer, /* pointer to the first character in the buffer */
  522.     *BuffEnd; /* pointer to the last character in the buffer */
  523. {
  524.     register char *MLineBegin, *MLineEnd;
  525.     
  526.     Desc->Success = 0;
  527.     /* Start points to first character after a successful match */
  528.     MLineBegin = MLineEnd = Desc->Start - 1;
  529.     while(MLineBegin >=Buffer && *MLineBegin != '\n') --MLineBegin;
  530.     ++MLineBegin;
  531.     while( MLineEnd <= BuffEnd && *MLineEnd != '\n') ++MLineEnd;
  532.     if (MLineEnd > BuffEnd) --MLineEnd;
  533.     /* fixed 25jun85 pdbain. suppress multiple matches of the same
  534.     * pattern on one line */
  535.     Desc->Start = MLineEnd + 1;
  536.     /* check if exact match */
  537.     if (xFlag && !( Desc->PatLen == (*MLineEnd != '\n' ? ((MLineEnd -
  538.     MLineBegin) + 1) : (MLineEnd - MLineBegin))))
  539.         return(0); /* failure */
  540.     if (sFlag) return(1);
  541.     if (cFlag) {
  542.         ++MatchCount;
  543.         return(1);
  544.     } /* if */
  545.     PrintLine(BuffPos+(Desc->Start-Buffer),MLineBegin,MLineEnd);
  546.     return(1);
  547. } /* MatchFound */
  548. SHAR_EOF
  549. if test 1181 -ne "`wc -c < 'MatchFound.c'`"
  550. then
  551.     echo shar: error transmitting "'MatchFound.c'" '(should have been 1181 characters)'
  552. fi
  553. fi
  554. echo shar: extracting "'MkDescVec.c'" '(831 characters)'
  555. if test -f 'MkDescVec.c'
  556. then
  557.     echo shar: will not over-write existing file "'MkDescVec.c'"
  558. else
  559. cat << \SHAR_EOF > 'MkDescVec.c'
  560. #include "match.h"
  561. #ifdef STRINGS  
  562. #include <strings.h>
  563. #else
  564. /* some systems use <strings.h>, others use <string.h> */
  565. #include <string.h>
  566. #endif
  567. #ifndef index
  568. /* some systems use "strchr" instead of "index" */
  569. #define index strchr
  570. #endif
  571. /* scan a newline-separated string of patterns and set up the
  572. * vector of descriptors, one pattern descriptor per pattern. 
  573. * Return the number of patterns */
  574. int
  575. MkDescVec(DescVec, Pats)
  576. struct PattDesc *DescVec[];
  577. char *Pats;
  578. {
  579.     int NPats = 0;
  580.     char *EndPat;
  581.     extern struct PattDesc *MakeDesc();
  582.     while (*Pats && (EndPat = index(Pats,'\n')) && NPats < MAXPATS) {
  583.         *EndPat = '\0';
  584.         DescVec[NPats] = MakeDesc(Pats);
  585.         Pats = EndPat + 1;
  586.         ++NPats;
  587.     } /* while */
  588.     if (*Pats && NPats < MAXPATS) {
  589.         DescVec[NPats] = MakeDesc(Pats);
  590.         ++NPats;
  591.     } /* if */
  592.     return(NPats);
  593. } /* MkDescVec */
  594. SHAR_EOF
  595. if test 831 -ne "`wc -c < 'MkDescVec.c'`"
  596. then
  597.     echo shar: error transmitting "'MkDescVec.c'" '(should have been 831 characters)'
  598. fi
  599. fi
  600. echo shar: extracting "'MoveResidue.c'" '(1280 characters)'
  601. if test -f 'MoveResidue.c'
  602. then
  603.     echo shar: will not over-write existing file "'MoveResidue.c'"
  604. else
  605. cat << \SHAR_EOF > 'MoveResidue.c'
  606. #include "match.h"
  607. /* Moves the text which has not been completely searched at the end of
  608. * the buffer to the beginning of the buffer
  609. * and returns number of bytes moved */
  610. int MoveResidue(DescVec, NPats,Buffer, BuffEnd)
  611. register struct PattDesc **DescVec;
  612. int NPats;
  613. char *Buffer, *BuffEnd;
  614. {
  615.     char *FirstStart;
  616.     register char *Residue;
  617.     /* use this declaration if you don't use "bcopy" */
  618.     register char *f, *t;
  619.     register int i;
  620.     int ResSize;
  621.  
  622.     FirstStart = BuffEnd;
  623.     /* find the earliest point which has not been
  624.     * completely searched */
  625.     for (i=0; i < NPats; i++) {
  626.         FirstStart = 
  627.             min(FirstStart, DescVec[i]-> Start );
  628.     } /* for */
  629.     /* now scan to the beginning of the line containing the
  630.     * unsearched text */
  631.     for (Residue = FirstStart; *Residue != '\n' &&
  632.     Residue >= Buffer; Residue--);
  633.     if (Residue < Buffer)
  634.         Residue = FirstStart;
  635.     else ++Residue;
  636.     /* now move the residue to the beginning of
  637.     * the file */
  638.     ResSize = BuffEnd - Residue + 1;
  639.     /* use this if you don't have "bcopy" */
  640.     t = Buffer; f = Residue;
  641. #ifdef BCOPY
  642.     bcopy(Residue, Buffer, ResSize);
  643. #else
  644.     for(i=ResSize;i;--i)
  645.         *t++ = *f++;
  646. #endif
  647.     /* now fix the status vectors */
  648.     for (i=0; i < NPats; i++) {
  649.         DescVec[i]->Start -= (Residue - Buffer);
  650.     } /* for */
  651.     return(ResSize);
  652. } /* MoveResidue */
  653. SHAR_EOF
  654. if test 1280 -ne "`wc -c < 'MoveResidue.c'`"
  655. then
  656.     echo shar: error transmitting "'MoveResidue.c'" '(should have been 1280 characters)'
  657. fi
  658. fi
  659. echo shar: extracting "'PrintLine.c'" '(968 characters)'
  660. if test -f 'PrintLine.c'
  661. then
  662.     echo shar: will not over-write existing file "'PrintLine.c'"
  663. else
  664. cat << \SHAR_EOF > 'PrintLine.c'
  665. #include <stdio.h>
  666. #ifdef STRINGS
  667. /* some systems use <strings.h>, others use <string.h> */
  668. #include <strings.h>
  669. #else
  670. #include <string.h>
  671. #endif
  672. #include "Extern.h"
  673. PrintLine(OffSet,LineStart,LineEnd)
  674. int OffSet; /* offset of LineStart from beginning of file */
  675. char *LineStart,
  676.     *LineEnd;
  677. {
  678.     char OffStr[80];
  679.     if (lFlag) {
  680.         if (strlen(FileName) > 76) {
  681.             fprintf(stderr,"match: filename too long\n");
  682.             exit(2);
  683.         } /* if */
  684.         if (strlen(FileName)) {
  685.             sprintf(OffStr,"%s\n",FileName);
  686.             write(1,OffStr,strlen(OffStr));
  687.         } /* if */
  688.         return;
  689.     } /* if */
  690.     if (FileName && !hFlag) {
  691.         if (strlen(FileName) > 76) {
  692.             fprintf(stderr,"match: filename too long\n");
  693.             exit(2);
  694.         } /* if */
  695.         sprintf(OffStr,"%s: ",FileName);
  696.         write(1,OffStr,strlen(OffStr));
  697.     } /* if */
  698.     if (nFlag) {
  699.         sprintf(OffStr,"%d: ",OffSet);
  700.         write(1,OffStr,strlen(OffStr));
  701.     } /* if */
  702.     write(1,LineStart,LineEnd-LineStart+1);
  703.     if (*LineEnd != '\n') write (1,"\n",1);
  704. } /* PrintLine */
  705. SHAR_EOF
  706. if test 968 -ne "`wc -c < 'PrintLine.c'`"
  707. then
  708.     echo shar: error transmitting "'PrintLine.c'" '(should have been 968 characters)'
  709. fi
  710. fi
  711. echo shar: extracting "'PutUsage.c'" '(774 characters)'
  712. if test -f 'PutUsage.c'
  713. then
  714.     echo shar: will not over-write existing file "'PutUsage.c'"
  715. else
  716. cat << \SHAR_EOF > 'PutUsage.c'
  717. #include <stdio.h>
  718. PutUsage()
  719. {
  720.     fprintf(stderr,
  721.     "match: search for a given string or strings in a file or files\n");
  722.     fprintf(stderr,
  723.     "synopsis: match [option]* [string(s)] [file]*\n");
  724.     fprintf(stderr,
  725.     "options:\n");
  726.     fprintf(stderr,
  727.     "-c print only a count of matching lines \n");
  728.     fprintf(stderr,
  729.     "-e Take next argument as the pattern\n");
  730.     fprintf(stderr,
  731.     "-f PFile read patterns from a file PFile\n");
  732.     fprintf(stderr,
  733.     "-h Do not print file names\n");
  734.     fprintf(stderr,
  735.     "-l print a list of files containing the pattern(s) \n");
  736.     fprintf(stderr,
  737.     "-n print the character offset of the pattern(s) \n");
  738.     fprintf(stderr,
  739.     "-s silent mode. Return only success (0) or failure (1)\n");
  740.     fprintf(stderr,
  741.     "-x print only lines which match entirely \n");
  742. } /*PutUsage */
  743. SHAR_EOF
  744. if test 774 -ne "`wc -c < 'PutUsage.c'`"
  745. then
  746.     echo shar: error transmitting "'PutUsage.c'" '(should have been 774 characters)'
  747. fi
  748. fi
  749. echo shar: extracting "'match.c'" '(2504 characters)'
  750. if test -f 'match.c'
  751. then
  752.     echo shar: will not over-write existing file "'match.c'"
  753. else
  754. cat << \SHAR_EOF > 'match.c'
  755. #include <stdio.h>
  756. #include <fcntl.h>
  757. #include <sys/file.h>
  758. #ifdef STRINGS
  759. /* some systems use <strings.h>, others use <string.h> */
  760. #include <strings.h>
  761. #else
  762. #include <string.h>
  763. #endif
  764. #include "match.h"
  765. #include "Extern.h"
  766. main(argc,argv)
  767. int argc;
  768. char *argv[];
  769. {
  770.     /* grep based on VAX MATCHC instruction */
  771.     char BigBuff[MAXBUFF + 2];
  772.     /*
  773.     * We leave one extra character at the beginning and end of the buffer,
  774.     * but don't tell Execute about it. This is so when someone is
  775.     * scanning the buffer and scans past the end (or beginning)
  776.     * we are still technically in the buffer (picky, but there ARE
  777.     * machines which would complain)
  778.     */
  779.     int ret = 1, /* return code from Execute */
  780.         NotFound = 0, /* non-zero if file not readable */
  781.         NFiles,
  782.         NPats; /* number of patterns to search for */
  783.     char i,
  784.         *FlagPtr,
  785.         **OptPtr; /* used to scan command line */
  786.     int TextFile /* file to search */;
  787.     struct PattDesc *DescVec[MAXPATS];
  788.  
  789.     --argc;
  790.     OptPtr = argv + 1;
  791.     while ( argc && **OptPtr == '-') {
  792.         FlagPtr = *OptPtr + 1;
  793.         while (*FlagPtr) {
  794.             switch (*FlagPtr) {
  795.                 case 'c': cFlag = 1; break;
  796.                 case 'e': eFlag = 1;
  797.                     /* get the patterns from next arg */
  798.                     NPats = MkDescVec(DescVec,*++OptPtr);
  799.                     --argc;
  800.                     break;
  801.                 case 'f': fFlag = 1; 
  802.                     /* read the patterns from a file */
  803.                     NPats = GetPatFile(*++OptPtr,DescVec);
  804.                     --argc;
  805.                     break;
  806.                 case 'l': lFlag = 1; break;
  807.                 case 'n': nFlag = 1; break;
  808.                 case 's': sFlag = 1; break;
  809.                 case 'x': xFlag = 1; break;
  810.                 case 'h': hFlag = 1; break;
  811.                 default:
  812.                     fprintf(stderr,
  813.                     "match: invalid option: -%c \n",
  814.                     *FlagPtr);
  815.                     PutUsage();
  816.                     exit(2);
  817.             } /* switch */
  818.             ++FlagPtr;
  819.         } /* while */
  820.         ++OptPtr; --argc;
  821.     } /* while */
  822.     /* OptPtr now points to patterns */
  823.     if (!fFlag && !eFlag) {
  824.         if (!argc) {
  825.             fprintf(stderr,"match: no pattern specified\n");
  826.             PutUsage();
  827.             exit(2);
  828.         } else
  829.             NPats = MkDescVec(DescVec,*OptPtr);
  830.         ++OptPtr; --argc;
  831.     }
  832.     /* OptPtr now points to first file */
  833.     NFiles = argc;
  834.     if (!NFiles)
  835.         ret &= Execute(DescVec,NPats,0,BigBuff+1);
  836.     else while (argc--) {
  837.         if ((NFiles > 1) || lFlag) FileName = *OptPtr;
  838.         if ((TextFile = open(*OptPtr,O_RDONLY,0)) < 0) {
  839.             fprintf(stderr,"match: can't open %s\n",*OptPtr);
  840.             NotFound++;
  841.         } else {
  842.             ret &= Execute(DescVec,NPats,TextFile,BigBuff+1);
  843.             if (sFlag && !ret)
  844.                 exit(0);
  845.             close(TextFile);
  846.         } /* if */
  847.         ++OptPtr;
  848.     } /* while */
  849.     if (cFlag) printf("%d\n",MatchCount);
  850.     exit(NotFound ? 2 : ret);
  851. } /* main */
  852. SHAR_EOF
  853. if test 2504 -ne "`wc -c < 'match.c'`"
  854. then
  855.     echo shar: error transmitting "'match.c'" '(should have been 2504 characters)'
  856. fi
  857. fi
  858. echo shar: extracting "'Extern.h'" '(616 characters)'
  859. if test -f 'Extern.h'
  860. then
  861.     echo shar: will not over-write existing file "'Extern.h'"
  862. else
  863. cat << \SHAR_EOF > 'Extern.h'
  864. /* global flags for bm */
  865. extern int    cFlag, /* true if we want only a count of matching lines */
  866.     eFlag, /* indicates that next argument is the pattern */
  867.     fFlag, /* true if the patterns arew to come from a file */
  868.     lFlag, /* true if we want a list of files containing the pattern */
  869.     nFlag, /* true if we want the character offset of the pattern */
  870.     sFlag, /* true if we want silent mode */
  871.     xFlag, /* true if we want only lines which match entirely */
  872.     hFlag, /* true if we want no filenames in output */
  873.  
  874.     MatchCount; /* count of number of times a search string was found
  875.     * in the text */
  876. extern char *FileName;
  877. SHAR_EOF
  878. if test 616 -ne "`wc -c < 'Extern.h'`"
  879. then
  880.     echo shar: error transmitting "'Extern.h'" '(should have been 616 characters)'
  881. fi
  882. fi
  883. echo shar: extracting "'match.h'" '(472 characters)'
  884. if test -f 'match.h'
  885. then
  886.     echo shar: will not over-write existing file "'match.h'"
  887. else
  888. cat << \SHAR_EOF > 'match.h'
  889. #define FIRSTCHAR ' '
  890. #define MAXCHAR 0377
  891. #define MAXBUFF 8192
  892. #define MAXSIZE 100
  893. #define MAXPATS 100 /* max number of patterns */
  894. #define PSIZEDEF 1024 /* default storage for patterns from a tty */
  895. #define min(x,y) ((x) < (y) ? (x) : (y))
  896. #define max(x,y) ((x) > (y) ? (x) : (y))
  897. struct PattDesc {
  898.     char *Pattern;
  899.     int PatLen; /* pattern length */
  900.     char *Start; /* starting position of search (at beginning of pattern) */
  901.     int Success; /* true when pattern found */
  902. };
  903. SHAR_EOF
  904. if test 472 -ne "`wc -c < 'match.h'`"
  905. then
  906.     echo shar: error transmitting "'match.h'" '(should have been 472 characters)'
  907. fi
  908. fi
  909. exit 0
  910. #    End of shell archive
  911.